#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# This program is free software; you can redistribute it and/or modify  
# it under the terms of the GNU General Public License as published by  
# the Free Software Foundation; either version 2 of the License, or     
# (at your option) any later version.                                   
#                                                                         
# A copy of the license can be found in the license.txt file supplied   
# with this software or at: http://www.gnu.org/copyleft/gpl.html       
#


from cell import Cell
from celtuce.event import Event, OP_FIND

from consts import TIMEOUT_WAIT_REPLY


from celtuce.response import Response, RC_TIMEOUT,RC_TABLE_NOT_FOUND,RC_CELL_NOT_FOUND

from celtuce.help import logging


class   Scanner(object) :
    def __init__(self, cell_keeper) :
        self._cell_keeper = cell_keeper

        self._id_base = id(self)
        self._id_serial = 1
        self._id_maximum = 1024 * 1024 * 1024

        self._logger = logging.getLogger('scanner')
        ## __init__()

    def find(self, table, key, timestamp_ms=0) :
        # STEP. find cell to host key
        response = self.lookupCell(table, key)
        if not response.isOk() :
            return response
        cell = response.body

        # STEP. find queue of cell
        response = self.lookupCellQueue(cell)
        if not response.isOk() :
            return response
        cell_queue = response.body

        # STEP. make request
        request = Event()
        request.request_id = self.genRequestID()
        request.response_to = 0 
        request.source_queue = self
        request.op = OP_FIND
        request.body = (table, key, timestamp_ms, cell.path)

        # STEP. put request into queue of cell
        reply = cell_queue.handle( request )

        # STEP. wait for reply
        response = reply.body
        if response is None :
            # timeout
            response = Response()
            response.status_code = RC_TIMEOUT
            response.error = 'Timeout to wait reply for request "%s"' % str(request)

        _record = response.body
        #if _record[3] is None :
        #    # just for debug
        #    self._logger.error('find nothing for key "%s" from table "%s"', key, table)
        #    self._logger.error('  locate cell "%s"', cell)
        #    self._cell_keeper.showRouteTable(table)

        return response
        ## find()

    ####-----------------------------------------------------------####

    def lookupCell(self, table, key) :
        return self._cell_keeper.lookupCell(table, key)
        ## lookupCell()

    def lookupCellQueue(self, cell) :
        return  self._cell_keeper.lookupCellQueue(cell)
        ## lookupCellQueue()

    ####-----------------------------------------------------------####

    def genRequestID(self) :
        # TODO: lock
        serial = self._id_serial

        self._id_serial += 1
        if self._id_serial >= self._id_maximum :
            self._id_serial = 1

        id = '.'.join((str(self._id_base), str(serial)))
        return id
        ## genRequestID()

    def waitReply(self, response_to) :
        reply = None
        while True :
            try :
                evt = self._event_queue.get(True, TIMEOUT_WAIT_REPLY)
                if evt.response_to == response_to :
                    reply = evt.body
                    self._event_queue.task_done()
                    break
                else :
                    self._event_queue.task_done()
            except queue.Empty :
                return None

        return reply
        ## waitReply()

    ## class Scanner

